import React, { useState } from 'react';
import { MenuItem, GridLegacy as Grid, Box } from '@mui/material';
import Tooltip from './Tooltip';
import Utils from '../../utils/Utils';
import { REAL_TYPE } from '../../constants';

interface NetPyNEFieldProps {
  id: string;
  mb?: number;
  model?: string;
  default?: any;
  children: React.ReactElement | React.ReactElement[];
  [key: string]: any;
}

const NetPyNEField: React.FC<NetPyNEFieldProps> = ({
  id,
  mb = 1,
  model,
  default: defaultProp,
  children,
  ...otherProps
}) => {
  const [open, setOpen] = useState(false);

  const setErrorMessage = (value: any): Promise<{ errorMsg: string }> => {
    return new Promise((resolve) => {
      const realType = Utils.getMetadataField(id, 'type');
      
      if (realType === REAL_TYPE.FUNC) {
        if (value !== '' && value !== undefined) {
          Utils.evalPythonMessage('netpyne_geppetto.validateFunction', [value]).then(
            (response: boolean) => {
              if (!response) {
                resolve({ errorMsg: 'Not a valid function' });
              } else {
                resolve({ errorMsg: '' });
              }
            }
          );
        } else {
          resolve({ errorMsg: '' });
        }
      } else if (realType === REAL_TYPE.FLOAT) {
        if (isNaN(value)) {
          resolve({ errorMsg: 'Only float allowed' });
        } else {
          resolve({ errorMsg: '' });
        }
      } else {
        resolve({ errorMsg: '' });
      }
    });
  };

  const prePythonSyncProcessing = (value: any): any => {
    if (value === '') {
      if (defaultProp !== undefined) {
        return defaultProp;
      }
      if (model && (!model.split('.')[0].startsWith('simConfig') || model.split('.')[1]?.startsWith('analysis'))) {
        Utils.execPythonMessage(`
        try:
          del netpyne_geppetto.${model}
        except KeyError:
          ...`);
      }
    }
    return value;
  };

  const handleTooltip = (action: boolean): void => {
    setOpen(action);
  };

  const help = Utils.getMetadataField(id, 'help');

  const childWithProp = React.Children.map(children, (child) => {
    if (!React.isValidElement(child)) return child;

    const extraProps: any = {};
    let name = (child.type as any)?.name || (child.type as any)?.muiName;
    
    if (name === undefined) {
      if ((child.type as any)?.options) {
        name = (child.type as any).options.name;
      }
    }

    if (
      [
        'Select',
        'TextField',
        'MuiFormControl',
        'Checkbox',
        'MuiTextField',
        'PythonControlledControlWithPythonDataFetch',
      ].indexOf(name) === -1
    ) {
      extraProps.validate = setErrorMessage;
      extraProps.prePythonSyncProcessing = prePythonSyncProcessing;

      const dataSource = Utils.getMetadataField(id, 'suggestions');
      if (dataSource !== '') {
        extraProps.dataSource = dataSource;
      }
    }

    const floatingLabelText = Utils.getMetadataField(id, 'label');
    extraProps.label = floatingLabelText;

    const type = Utils.getHTMLType(id);
    if (type !== '') {
      extraProps.type = type;
    }

    let realType;
    if (name === 'PythonControlledControl') {
      realType = Utils.getMetadataField(id, 'type');
      extraProps.realType = realType;
    }

    let defaultValue = Utils.getMetadataField(id, 'default');
    if (defaultValue) {
      if (realType === REAL_TYPE.DICT || realType === REAL_TYPE.DICT_DICT) {
        try {
          defaultValue = JSON.parse(defaultValue);
        } catch (e) {
          // Handle parse error
        }
      }
      extraProps.default = defaultValue;
    }

    const options = Utils.getMetadataField(id, 'options');
    if (options && Array.isArray(options)) {
      extraProps.children = options.map((name: string) => (
        <MenuItem id={name} key={name} value={name}>
          {name}
        </MenuItem>
      ));
    }

    return React.cloneElement(child, { ...extraProps, ...otherProps });
  });

  return (
    <Grid container alignItems="center">
      <Grid item>
        {help !== undefined && help !== '' ? (
          <Tooltip
            title={help}
            placement="top-end"
            enterDelay={2000}
            enterTouchDelay={2000}
            enterNextDelay={2000}
            leaveTouchDelay={0}
            disableTouchListener
            disableFocusListener
            open={open}
          >
            <Box
              mb={mb}
              width="100%"
              onMouseEnter={() => handleTooltip(true)}
              onMouseLeave={() => handleTooltip(false)}
              onClick={() => handleTooltip(false)}
            >
              {childWithProp}
            </Box>
          </Tooltip>
        ) : (
          <Box mb={mb} width="100%">
            {childWithProp}
          </Box>
        )}
      </Grid>
    </Grid>
  );
};

export default NetPyNEField;

